import { createAction } from 'redux-actions';
import { message } from 'antd';
import * as Immutable from 'seamless-immutable';
import * as _ from 'lodash';
import { ThunkAction } from 'redux';
import * as API from '../../config/api';


// define const var
export const localStorageKey = {
  _token: 'spa_token',
  _sessionId: 'spa_jsessionid',
  _loginSessionId: 'spa_loginsessionid',
  clear: () => {
    localStorage.removeItem(localStorageKey._token)
    localStorage.removeItem(localStorageKey._sessionId)
  },
  setToken: (val: string) => {
    localStorage.setItem(localStorageKey._token, val);
  },
  setSessionId: (val: string) => {
    localStorage.setItem(localStorageKey._sessionId, val);
  },
  setLoginSessionId: (val: string) => {
    localStorage.setItem(localStorageKey._loginSessionId, val);
  },
  getToken: (): string => {
    return localStorage.getItem(localStorageKey._token);
  },
  getSessionId: (): string => {
    return localStorage.getItem(localStorageKey._sessionId);
  },
  getLoginSessionId: (): string => {
    return localStorage.getItem(localStorageKey._loginSessionId);
  }
};
//define util function
const parseParam = (params: any): string => {
  let str: any[] = [];
  for (var key in params) {
    var encodedKey = encodeURIComponent(key);
    var encodedValue = encodeURIComponent(params[key]);
    str.push(encodedKey + "=" + encodedValue);
  }
  return str.join('&');
}

export const readyToLogin = createAction('READY_TO_LOGIN')
// define action
const logoutStart = createAction('LOGOUT_START')
const logoutSuccess = createAction('LOGOUT_SUCCESS')
// const logoutFailure = createAction('LOGOUT_FAILURE')

// export logout action
export const logout = (): ThunkAction<void, any, any> => (dispatch, getState) => {
  dispatch(logoutStart());
  const closeLoading = message.loading('登出中...', 0);
  setTimeout(() => {
    localStorageKey.clear();
    setTimeout(closeLoading, 0);
    dispatch(logoutSuccess());
  }, 2000)
}



// define action
const loginWithTokenStart = createAction('LOGIN_WITH_TOKEN_START')
const loginWithTokenSuccess = createAction('LOGIN_WITH_TOKEN_SUCCESS')
const loginWithTokenFailure = createAction('LOGIN_WITH_TOKEN_FAILURE')
// export loginWithToken action
export const loginWithToken = (tokenUrl: string, loginSessionId: string): ThunkAction<void, any, any> => (dispatch, getState) => {
  // TODO
  dispatch(loginWithTokenSuccess({}));

  dispatch(loginWithTokenStart());
  const closeLoading = message.loading('加载中...', 0);

  const params = parseParam({
    loginSessionId,
    service: API.URI.system.user.captchas,
  })

  API.myFetch.get(tokenUrl, {
    body: params
  }, true).then(result => {
    return result.json();
  }).then(data => {
    setTimeout(closeLoading, 0);
    if (data.success) {
      API.myFetch.get(API.URI.system.user.loginTicket, null, true).then(result => {
        const { url } = result;
        const term = ';jsessionid='
        const jsessionid = url.substring(url.indexOf(term) + term.length);
        localStorageKey.setSessionId(jsessionid);
      });
      dispatch(loginWithTokenSuccess(data))
    } else {
      dispatch(loginWithTokenFailure(data))
    }
  }).catch(error => {
    // dispatch(loginWithTokenFailure(error))
    //TODO
    setTimeout(closeLoading, 0)
    dispatch(loginWithTokenSuccess({}))
  });
}

const getCaptchaStart = createAction('GET_CAPTCHA_START')
const getCaptchaSuccess = createAction('GET_CAPTCHA_SUCCESS')
const getCaptchaFailure = createAction('GET_CAPTCHA_FAILURE')

export const getCaptcha = (): ThunkAction<void, any, any> => (dispatch, getState) => {
  dispatch(getCaptchaStart());
  API.myFetch.post(API.URI.system.user.captchas, null, true).then(res => {
    return res.json();
  }).then(result => {
    if (result.success) {
      dispatch(getCaptchaSuccess(result));
    } else {
      dispatch(getCaptchaFailure(result));
    }
  }).catch(error => {
    dispatch(getCaptchaFailure(error));
  })
}

const loginStart = createAction('LOGIN_START');
const loginSuccess = createAction('LOGIN_SUCCESS');
const loginFailure = createAction('LOGIN_FAILURE');

export const login = (): ThunkAction<void, any, any> => (dispatch, getState) => {
  //TODO
  localStorageKey.setToken("http://www.baidu.com");
  localStorageKey.setLoginSessionId("for_test_session");
  dispatch(loginSuccess({}))

  const closeLoading = message.loading('登录中...', 0);
  dispatch(loginStart())

  const { loginId, username, password, captcha, loginSessionId } = getState().authReducer;
  const params = _.pick(getState().authReducer, ['loginId', 'username', 'password', 'captcha', 'loginSessionId'])
  const body = parseParam(params)


  API.myFetch.get(API.URI.system.user.loginTicket, {
    body: body
  }, true).then(response => {
    if (response.status === 201) {
      return response.text()
    }
  }).then(html => {
    //TODO
    if (!html) {
      localStorageKey.setToken("http://www.baidu.com");
      localStorageKey.setLoginSessionId("for_test_session");
      dispatch(loginSuccess({}))
      return;
    }

    // get post location
    const el = document.createElement('html')
    el.innerHTML = html
    const form = el.getElementsByTagName('form')[0]
    const tokenUrl = form.action

    // create post body
    const loginSessionId = getState().authReducer.loginSessionId
    const params = parseParam({
      loginSessionId,
      service: API.URI.system.user.captchas,
    })

    API.myFetch.get(tokenUrl, {
      body: params
    }, true).then(result => {
      return result.json()
    }).then(data => {
      setTimeout(closeLoading, 0)
      if (data.success) {
        const ticket = data.ticket
        API.myFetch.get(API.URI.system.user.loginTicket, null, true).then(result => {
          const { url } = result;
          const term = ';jsessionid='
          const jsessionid = url.substring(url.indexOf(term) + term.length);
          localStorageKey.setSessionId(jsessionid);
        });

        localStorageKey.setLoginSessionId(loginSessionId);
        localStorageKey.setToken(tokenUrl);
        dispatch(loginSuccess(data));
      } else {
        dispatch(loginFailure(data));
      }
    }).catch(error => {
      dispatch(loginFailure(error));
    })
  })
}

export const setFormData = createAction<any>('SET_FORM_DATA', (key, value) => ({
  key,
  value
}));